package JavaSE.AnnotationLearning.ReflectTest2;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;

public class StudentFactory {
    private Class studentClass;
    private PrintWriter pw;

    public StudentFactory() throws IOException {
        this.studentClass = Student.class;
        this.pw = new PrintWriter(
                new FileWriter("src\\JavaSE\\AnnotationLearning\\ReflectTest2\\Exception.txt"));
    }

    public Student getStudent(int age, String name) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        // 利用注解进行判断
        // 年龄判断
        judgeAge(age);

        // 名字判断
        judgeName(name);

        // 关闭输出流
        pw.close();

        // 通过反射实例化
        // 获取构造器
        Constructor declaredConstructor = studentClass.getDeclaredConstructor(int.class, String.class);
        // 暴力访问
        declaredConstructor.setAccessible(true);
        // 使用构造方法创建对象并强制转型
        Student stu1 = ((Student) declaredConstructor.newInstance(age, name));
        return stu1;
    }

    private void judgeAge(int age) throws NoSuchFieldException {
        // 获取class对象中的变量信息
        Field ageField = studentClass.getDeclaredField("age");
        // 判断这个变量上是否有相关注解
        boolean ageAnnoFlag = ageField.isAnnotationPresent(AgeBound.class);
        if(ageAnnoFlag) {
            // 获取注解实例对象
            AgeBound ageBound = ageField.getAnnotation(AgeBound.class);
            if(age>ageBound.maxAge() || age<ageBound.minAge()) {
                try{
                    throw new IllegalArgumentException("非法年龄输入，输入为：" + age);
                } catch (Exception e) {
                    printException(e);
                    e.printStackTrace();
                }
            }
        }
    }

    private void judgeName(String name) throws NoSuchFieldException {
        // 获取class对象中的变量信息
        Field nameField = studentClass.getDeclaredField("name");
        // 判断这个变量上是否有相关注解
        boolean nameAnnoFlag = nameField.isAnnotationPresent(NameBound.class);
        if(nameAnnoFlag) {
            // 获取注解实例对象
            NameBound nameBound = nameField.getAnnotation(NameBound.class);
            if(name.length() > nameBound.limit()) {
                try{
                    throw new IllegalArgumentException("非法姓名输入，输入为：" + name);
                } catch (Exception e) {
                    printException(e);
                    e.printStackTrace();
                }
            }
        }
    }

    private void printException(Exception e) {
        pw.println("-----------------------------------------------------------------");
        e.printStackTrace(pw);
        pw.println("-----------------------------------------------------------------");
        pw.flush();
    }
}
